;;; -*- lexical-binding: t -*-

(require 'project)
(require 'consult)


(defun ctrlwei-project-buffer--file-preview ()
  "Create preview function for project files."
  (let ((open (consult--temporary-files))
        (preview (consult--buffer-preview)))
    (lambda (action cand)
      (unless cand
        (funcall open))
      (funcall preview action
               (and cand
                    (eq action 'preview)
                    (funcall open (concat (project-root (project-current)) cand)))))))

(defvar ctrlwei-project-buffer--source-buffer
  `(:name     "Project Buffer"
              :narrow   (?b . "Buffer")
              :category buffer
              :face     consult-buffer
              :history  buffer-name-history
              :state    ,#'consult--buffer-state
              :items
              ,(lambda ()
                 (when-let* ((root (project-root (project-current))))
                   (consult--buffer-query :sort 'visibility
                                          :directory (expand-file-name root)
                                          :as #'buffer-name)))))

(defvar ctrlwei-project-buffer--source-file
  `(:name      "Project File"
               :narrow    (?f . "File")
               :category  project-file
               :face      consult-file
               :preview-key "M-."
               :state     ,#'ctrlwei-project-buffer--file-preview
               :action    ,(lambda (file-name) (find-file (concat (project-root (project-current)) file-name)))
               :items
               ,(lambda ()
                  (let* ((root (project-root (project-current)))
                         (project (project--find-in-directory root))
                         (files (project-files project)))
                    (mapcar (lambda (f) (file-relative-name f root)) files)))))

(defvar ctrlwei-project-buffer--source-project
  `(:name      "Known Project"
               :narrow    (?p . "Project")
               :category  file
               :face      consult-file
               :items     ,#'project-known-project-roots
               :action
               ,(lambda (dir) (let ((project-current-directory-override dir))
                                (ctrlwei/project-buffer)))))

(setq ctrlwei-project-buffer-sources
      (list ctrlwei-project-buffer--source-buffer
            ctrlwei-project-buffer--source-file
            ctrlwei-project-buffer--source-project
            consult--source-hidden-buffer))


;;;###autoload
(defun ctrlwei/project-buffer ()
  (interactive)
  (if (project-current)
      (consult--with-project
       (consult-buffer ctrlwei-project-buffer-sources))
    (project-find-file)))

(provide 'ctrlwei-project-extra)
